Навигация между экранами
➡️Ссылка на репозиторий с кодом этого урока
Таблица маршрутизации
При большом количестве экранов используется таблица маршрутизации.
С помощью таблицы маршрутизации устанавливается соответствие между именами маршрутов и виджетами экранов.
Указывается таблица внутри виджета MaterialApp в параметр routes
Файл main.dart
import 'package:flutter/material.dart';
import 'screens/main_screen.dart';
import 'screens/first_screen.dart';
import 'screens/second_screen.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Навигация в Flutter',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
initialRoute: '/main', // Этот экран запустится первым
routes: {
'/main': (context) => MainScreen(),
'/first': (context) => FirstScreen(),
'/second': (context) => SecondScreen(),
},
);
}
}
initialRoute: '/main'теперь вместо home: const MainScreen()initialRouteэто начальный экранNavigator.pushNamed()более простой и красивый метод для перехода на другой экран
Например, чтобы теперь перейти с экрана MainScreen на экран FirstScreen в обработчике нажатия на кнопку пишем этот код:
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, '/first'),
child: const Text("Открыть FirstScreen"),
),
Файл main_screen.dart
import 'package:flutter/material.dart';
class MainScreen extends StatelessWidget {
const MainScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Главный экран'), centerTitle: true),
backgroundColor: Colors.white,
body: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, '/first'),
child: const Text("Открыть FirstScreen"),
),
],
),
),
);
}
}
Файл first_screen.dart
import 'package:flutter/material.dart';
class FirstScreen extends StatelessWidget {
const FirstScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Первый экран'),
backgroundColor: Colors.green[300],
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFFBFF098), Color(0xFF6FD6FF)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, '/second'),
child: const Text("Открыть 2й экран"),
),
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text("Вернуться Назад"),
),
],
),
),
),
);
}
}
Наименование роутов
В данной таблице названия роутов прописаны вручную /main /first /second
routes: {
'/main': (context) => MainScreen(),
'/first': (context) => FirstScreen(),
'/second': (context) => SecondScreen(),
},
Когда экранов условно 3-5 такой подход нормальный. Но когда их становится 30-50, можно легко ошибиться, забыть название и сделать другие косяки.
Поэтому рекомендуется указывать имя роута внутри самого класса как static значение
Файл main_screen.dart
class MainScreen extends StatelessWidget {
static const routeName = '/main'; // Указываем имя экрана
// ...
Файл first_screen.dart
class FirstScreen extends StatelessWidget {
static const routeName = '/first'; // Указываем имя экрана
// ...
Файл second_screen.dart
class SecondScreen extends StatelessWidget {
static const routeName = '/second'; // Указываем имя экрана
// ...
Теперь внутри таблицы маршрутизации указываем так
Файл main.dart
import 'package:flutter/material.dart';
import 'screens/main_screen.dart';
import 'screens/first_screen.dart';
import 'screens/second_screen.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Навигация в Flutter',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
initialRoute: MainScreen.routeName,
routes: {
MainScreen.routeName: (context) => MainScreen(),
FirstScreen.routeName: (context) => FirstScreen(),
SecondScreen.routeName: (context) => SecondScreen(),
},
);
}
}
Обработчики нажатия тоже нужно изменить
Файл main_screen.dart
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, FirstScreen.routeName),
child: const Text("Открыть FirstScreen"),
),
Файл first_screen.dart
ElevatedButton(
onPressed: () => Navigator.pushNamed(context, SecondScreen.routeName),
child: const Text("Открыть 2й экран"),
),